<template>
  <div class="sphere-face-3d" :style="{ width: renderParams.width + 'px', height: renderParams.height + 'px' }">
    <div class="title">
      鼠标 x:{{ mousePosition.x.toFixed(1) }} y:{{ mousePosition.y.toFixed(1) }} z:{{ mousePosition.z.toFixed(1) }}
    </div>
    <div ref="threeBoxRef" class="view-content"></div>
    <!-- 传感器编号显示 -->
    <template v-for="(sensor, index) in sensors" :key="sensor.id">
      <div class="sensor-label" :style="sensor.dynamicStyle">
        {{ sensor.id }}
      </div>
    </template>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, defineProps, defineExpose, onUnmounted, reactive } from 'vue';
import { LocateSetData } from '@/utils/appCommon/appCommonOptions/aeLocateConfigModel';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry';
import { computeScaleRate } from "@/views/apply/locateAnalysis/component/utils/commonThree";

// 定义接收的props
const props = defineProps<{
  locateSetting: LocateSetData;
  renderParams: {
    width: number;
    height: number;
    viewMode: number;
  };
  searchParams: any;
}>();

// 参考d3-bak.vue中的状态管理
const threeBoxRef = ref();
const threeData = reactive({
  width: 600,
  height: 600,
  bgColor: '#f0f4f8',
  scaleRate: 1 // 用于实际尺寸和3D尺寸之间的转换
});

// 鼠标位置状态
const mousePosition = reactive({
  x: 0,
  y: 0,
  z: 0
});

// 传感器和点的数据结构
const sensors = ref<Array<{
  id: number;
  longitude: number;
  latitude: number;
  cube: THREE.Mesh;
  dynamicStyle: {
    left: string;
    top: string;
    display: string;
  };
}>>([]);

const points = ref<Array<{
  id: string;
  position: THREE.Vector3;
  mesh: THREE.Mesh;
}>>([]);

// Three.js 核心对象
let scene: THREE.Scene | null = new THREE.Scene();
let camera: THREE.PerspectiveCamera | null = new THREE.PerspectiveCamera();
let renderer: THREE.WebGLRenderer | null = new THREE.WebGLRenderer({ antialias: true });
let controls: OrbitControls | null = null;
let sphereMesh: THREE.Mesh | null = null;
let raycaster = new THREE.Raycaster();
let mouse = new THREE.Vector2();

// 坐标轴相关
let axisLineMeshes: THREE.Object3D[] = [];
let axisTextMeshes: THREE.Object3D[] = [];
let axisLabelFont: any = null;

// 传感器计数器
let sensorCounter = 1;

// 初始化Three.js场景
function initThree() {
  if (!threeBoxRef.value) return;

  // 首先更新threeData的尺寸，确保使用最新的renderParams
  threeData.width = props.renderParams.width;
  threeData.height = props.renderParams.height;

  // 创建场景
  scene.background = new THREE.Color(threeData.bgColor);

  // 创建渲染器
  renderer.setSize(threeData.width, threeData.height);
  threeBoxRef.value.innerHTML = '';
  threeBoxRef.value.appendChild(renderer.domElement);

  // 创建相机
  const cameraY = threeData.width > 100 ? threeData.width : 100;
  camera.position.set(0, -cameraY, 0); // 初始相机位置
  camera.aspect = threeData.width / threeData.height;
  camera.updateProjectionMatrix();
  camera.lookAt(scene.position); // 指向原点

  // 添加轨道控制器
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.dampingFactor = 0.05;
  controls.addEventListener('change', () => {
    updateAllSensorLabels();
  });

  // 添加光源
  const light = new THREE.DirectionalLight(0xffffff, 1);
  light.position.set(0, threeData.width, threeData.height);
  scene.add(light);

  // 添加鼠标移动监听
  window.addEventListener('mousemove', handleMouseMove);

  // 初始化球体和坐标轴
  updateSphere();
}

// 更新球体
function updateSphere() {
  if (!scene) return;

  // 移除旧的球体
  if (sphereMesh) {
    scene.remove(sphereMesh);
  }

  const radius = getSphereRadius();

  // 创建球体几何体
  const geometry = new THREE.SphereGeometry(radius, 32, 32);

  // 创建材质 - 保持一致的纹理和透明度
  const material = new THREE.MeshBasicMaterial({
    color: 0xdadada,
    wireframe: false,
    transparent: true,
    opacity: 0.9
  });

  sphereMesh = new THREE.Mesh(geometry, material);
  // 旋转-90度以匹配d3-bak.vue的显示效果
  sphereMesh.rotation.x = -Math.PI / 2;
  scene.add(sphereMesh);

  // 创建坐标轴
  createAxis();

  // 渲染场景
  render();
}

// 获取球体半径
function getSphereRadius(): number {
  const radius = props.locateSetting?.config?.modelConfig?.radius || 100;
  // 计算缩放率，参考d3-bak.vue
  const scaleRate = computeScaleRate(radius * 2, 300); // 300作为比较尺寸
  threeData.scaleRate = scaleRate;
  // 转换为3D视图中的半径
  return Math.max(radius / scaleRate, 1);
}


// 创建坐标轴 - 参考d3-bak.vue实现
function createAxis() {
  if (!scene) return;

  // 清除现有的坐标轴
  if (axisLineMeshes.length > 0) {
    axisLineMeshes.forEach(item => {
      item.removeFromParent();
    });
    axisLineMeshes = [];
  }

  if (axisTextMeshes.length > 0) {
    axisTextMeshes.forEach(item => {
      item.removeFromParent();
    });
    axisTextMeshes = [];
  }

  // 加载字体
  const fontLoader = new FontLoader();
  fontLoader.load('/public/threefont.json', function(font) {
    axisLabelFont = font;
    createAxisHelper(font);
  });
}

// 创建坐标轴辅助 - 参考d3-bak.vue实现
function createAxisHelper(font: any) {
  if (!scene) return;

  // 创建材质
  const materialX = new THREE.LineBasicMaterial({ color: 0xff0000 }); // 红色X轴
  const materialY = new THREE.LineBasicMaterial({ color: 0x00ff00 }); // 绿色Y轴
  const materialZ = new THREE.LineBasicMaterial({ color: 0x0000ff }); // 蓝色Z轴

  const radius = getSphereRadius();
  const xmin = 0;
  const xmax = radius;
  const xstep = xmax / 5;

  const ymin = 0;
  const ymax = radius;
  const ystep = ymax / 5;

  const zmin = 0;
  const zmax = radius;
  const zstep = zmax / 5;

  // X轴刻度和标签
  for (let i = xmin; i <= xmax + xstep; i += xstep) {
    // 刻度线
    const geometry = new THREE.BufferGeometry();
    const positions = new Float32Array([
      i, 0, 0,
      i, 0.2, 0
    ]);
    geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    const line = new THREE.Line(geometry, materialX);
    axisLineMeshes.push(line);
    scene?.add(line);

    // 标签
    if (i > 0) {
      const textLabel = Math.round(i * threeData.scaleRate).toString();
      const textGeometry = new TextGeometry(textLabel, {
        font: font,
        size: xstep / 4,
        height: 0.01
      });
      const textMaterial = new THREE.MeshBasicMaterial({ color: 0x888888 });
      const textMesh = new THREE.Mesh(textGeometry, textMaterial);
      textMesh.position.set(i, -0.5, 0.2);
      axisTextMeshes.push(textMesh);
      scene?.add(textMesh);
    }
  }

  // Y轴刻度和标签
  for (let i = ymin; i <= ymax + ystep; i += ystep) {
    // 刻度线
    const geometry = new THREE.BufferGeometry();
    const positions = new Float32Array([
      0, i, 0,
      0.2, i, 0
    ]);
    geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    const line = new THREE.Line(geometry, materialY);
    axisLineMeshes.push(line);
    scene?.add(line);

    // 标签
    if (i > 0) {
      const textLabel = Math.round(i * threeData.scaleRate).toString();
      const textGeometry = new TextGeometry(textLabel, {
        font: font,
        size: ystep / 4,
        height: 0.01
      });
      const textMaterial = new THREE.MeshBasicMaterial({ color: 0x888888 });
      const textMesh = new THREE.Mesh(textGeometry, textMaterial);
      textMesh.position.set(-0.5, i, 0.2);
      axisTextMeshes.push(textMesh);
      scene?.add(textMesh);
    }
  }

  // Z轴刻度和标签
  for (let i = zmin; i <= zmax + zstep; i += zstep) {
    // 刻度线
    const geometry = new THREE.BufferGeometry();
    const positions = new Float32Array([
      0, 0, i,
      0.2, 0, i
    ]);
    geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    const line = new THREE.Line(geometry, materialZ);
    axisLineMeshes.push(line);
    scene?.add(line);

    // 标签
    if (i > 0) {
      const textLabel = Math.round(i * threeData.scaleRate).toString();
      const textGeometry = new TextGeometry(textLabel, {
        font: font,
        size: zstep / 4,
        height: 0.01
      });
      const textMaterial = new THREE.MeshBasicMaterial({ color: 0x888888 });
      const textMesh = new THREE.Mesh(textGeometry, textMaterial);
      textMesh.position.set(-0.5, 0.2, i);
      axisTextMeshes.push(textMesh);
      scene?.add(textMesh);
    }
  }

  // XYZ轴线
  // X轴
  const xAxisGeometry = new THREE.BufferGeometry();
  const xAxisPositions = new Float32Array([
    xmin, 0, 0,
    xmax + xstep, 0, 0
  ]);
  xAxisGeometry.setAttribute('position', new THREE.BufferAttribute(xAxisPositions, 3));
  const xAxisLine = new THREE.Line(xAxisGeometry, materialX);
  axisLineMeshes.push(xAxisLine);
  scene?.add(xAxisLine);

  // Y轴
  const yAxisGeometry = new THREE.BufferGeometry();
  const yAxisPositions = new Float32Array([
    0, ymin, 0,
    0, ymax + ystep, 0
  ]);
  yAxisGeometry.setAttribute('position', new THREE.BufferAttribute(yAxisPositions, 3));
  const yAxisLine = new THREE.Line(yAxisGeometry, materialY);
  axisLineMeshes.push(yAxisLine);
  scene?.add(yAxisLine);

  // Z轴
  const zAxisGeometry = new THREE.BufferGeometry();
  const zAxisPositions = new Float32Array([
    0, 0, zmin,
    0, 0, zmax + zstep
  ]);
  zAxisGeometry.setAttribute('position', new THREE.BufferAttribute(zAxisPositions, 3));
  const zAxisLine = new THREE.Line(zAxisGeometry, materialZ);
  axisLineMeshes.push(zAxisLine);
  scene?.add(zAxisLine);

  render();
}

// 经纬度转换为3D坐标
// geoTo3D函数返回的位置是否正确
function geoTo3D(longitude: number, latitude: number): THREE.Vector3 {
  const radius = getSphereRadius();
  // 确保正确的经纬度转换
  return rawPlaneTo3DSpherical(longitude, latitude, radius);
}

// 原始平面坐标到3D球面坐标的转换 - 参考d3-bak.vue
function rawPlaneTo3DSpherical(u: number, v: number, R: number): THREE.Vector3 {
  // 将平面坐标转换为经纬度
  let lambda = u - 180;  // 经度，从-180到180度
  let phi = 90 - v;      // 纬度，从90到-90度

  // 转换为弧度
  let lambdaRad = lambda * Math.PI / 180;
  let phiRad = phi * Math.PI / 180;

  // 转换为三维坐标
  let x = R * Math.cos(phiRad) * Math.cos(lambdaRad);
  let y = R * Math.cos(phiRad) * Math.sin(lambdaRad);
  let z = R * Math.sin(phiRad);

  // 调整Y轴方向，与d3-bak.vue保持一致
  return new THREE.Vector3(x, -y, z);
}

// 3D坐标转换为经纬度
function threeDToGeo(x: number, y: number, z: number): { longitude: number; latitude: number } {
  const radius = Math.sqrt(x * x + y * y + z * z);

  // 调整Y轴方向
  y = -y;

  // 计算经度和纬度（弧度）
  const longitudeRad = Math.atan2(y, x);
  const phiRad = Math.acos(z / radius);

  // 转换为度数
  let longitude = (longitudeRad / Math.PI) * 180 + 180; // 转换为0-360范围
  let latitude = 90 - (phiRad / Math.PI) * 180; // 转换为0-180范围

  // 确保范围正确
  longitude = longitude % 360;
  latitude = Math.max(0, Math.min(180, latitude));

  return { longitude, latitude };
}

// 创建传感器立方体
function createSensorCube(size: number): THREE.Mesh {
  const cubeGeometry = new THREE.BoxGeometry(size, size, size);
  // 使用更明显的蓝色，并增加透明度以更好地显示
  const material = new THREE.MeshBasicMaterial({
    color: "#0000ee",
  });
  const cube = new THREE.Mesh(cubeGeometry, material);
  return cube;
}

// 添加传感器
function addSensor(longitude: number, latitude: number): number {
  if (!scene) return -1;

  const id = sensorCounter++;

  // 获取球体半径
  const radius = getSphereRadius();

  // 使用经纬度转换为3D坐标，确保传感器位于球面上
  const position = geoTo3D(longitude, latitude);

  // 增大传感器立方体尺寸，确保可见性
  const cube = createSensorCube(4);

  // 计算传感器的正确位置
  const direction = position.clone().normalize();

  // 将传感器位置设置为球体表面，并稍微向外移动一点以确保可见
  const finalPosition = direction.clone().multiplyScalar(radius + 0.05);
  cube.position.copy(finalPosition);

  // 添加到场景
  scene.add(cube);

  // 检查可见性
  const isVisible = judgeSensorVisible(cube);

  // 添加传感器数据
  sensors.value.push({
    id,
    longitude,
    latitude,
    cube,
    dynamicStyle: {
      left: '0px',
      top: '0px',
      display: isVisible ? 'block' : 'none'
    }
  });

  // 更新标签位置
  updateSensorLabel(sensors.value.length - 1);

  render();
  return id;
}

// 删除传感器
function removeSensor(id: number): boolean {
  if (!scene) return false;

  const index = sensors.value.findIndex(sensor => sensor.id === id);
  if (index === -1) return false;

  // 移除3D对象
  scene.remove(sensors.value[index].cube);

  // 从数组中删除
  sensors.value.splice(index, 1);

  render();
  return true;
}

// 添加点
function addPoint(x: number, y: number, z: number, id?: string): string {
  if (!scene) return '';

  const pointId = id || `point_${Date.now()}`;
  const position = new THREE.Vector3(x, y, z);

  // 创建点的几何体
  const pointGeometry = new THREE.SphereGeometry(1, 8, 8);
  const pointMaterial = new THREE.MeshBasicMaterial({ color: "#ff0000" }); // 红色点
  const pointMesh = new THREE.Mesh(pointGeometry, pointMaterial);
  pointMesh.position.copy(position);
  scene.add(pointMesh);

  // 存储点信息
  points.value.push({
    id: pointId,
    position,
    mesh: pointMesh
  });

  render();
  return pointId;
}

// 移除点
function removePoint(id: string): boolean {
  if (!scene) return false;

  const index = points.value.findIndex(point => point.id === id);
  if (index === -1) return false;

  // 移动物体
  scene.remove(points.value[index].mesh);

  // 从数组中删除
  points.value.splice(index, 1);

  render();
  return true;
}

// 判断传感器是否可见（是否被遮挡）- 参考d3-bak.vue实现
function judgeSensorVisible(sensor: THREE.Mesh): boolean {
  if (!sphereMesh || !camera) return true;

  // 获取球体和传感器的世界位置
  const sphereWorldPosition = new THREE.Vector3();
  sphereMesh.getWorldPosition(sphereWorldPosition);

  const sensorWorldPosition = new THREE.Vector3();
  sensor.getWorldPosition(sensorWorldPosition);

  const cameraWorldPosition = new THREE.Vector3();
  camera.getWorldPosition(cameraWorldPosition);

  // 计算球体中心到相机的向量和球体中心到传感器的向量
  const sphereToCameraVector = new THREE.Vector3().subVectors(cameraWorldPosition, sphereWorldPosition);
  const sphereToSensorVector = new THREE.Vector3().subVectors(sensorWorldPosition, sphereWorldPosition);

  // 归一化向量
  sphereToCameraVector.normalize();
  sphereToSensorVector.normalize();

  // 使用点积判断方向
  const dotProduct = sphereToCameraVector.dot(sphereToSensorVector);

  // 如果点积小于0，说明传感器在球体背面
  return dotProduct >= 0;
}

// 更新传感器标签位置
function updateSensorLabel(index: number) {
  if (!camera || !scene) return;

  const sensor = sensors.value[index];
  if (!sensor) return;

  // 将3D位置转换为屏幕坐标
  const vector = new THREE.Vector3();
  sensor.cube.getWorldPosition(vector);
  vector.project(camera);

  const x = (vector.x * 0.5 + 0.5) * threeData.width;
  const y = (-vector.y * 0.5 + 0.5) * threeData.height;

  // 更新样式
  sensor.dynamicStyle.left = `${x}px`;
  sensor.dynamicStyle.top = `${y}px`;

  // 判断是否可见
  sensor.dynamicStyle.display = judgeSensorVisible(sensor.cube) ? 'block' : 'none';
}

// 更新所有传感器标签
function updateAllSensorLabels() {
  sensors.value.forEach((_, index) => {
    updateSensorLabel(index);
  });
  render();
}

// 处理鼠标移动
function handleMouseMove(event: MouseEvent) {
  if (!renderer || !camera || !scene) return;

  const rect = renderer.domElement.getBoundingClientRect();
  const x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
  const y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

  mouse.set(x, y);
  raycaster.setFromCamera(mouse, camera);

  // 使用光线投射器来获取与射线相交的物体
  const intersects = raycaster.intersectObjects(scene.children, true);
  if (intersects.length > 0) {
    const intersection = intersects[0];
    const position = intersection.point;

    // 应用缩放率并更新鼠标位置
    mousePosition.x = Number(position.x) * threeData.scaleRate;
    mousePosition.y = Number(position.y) * threeData.scaleRate;
    mousePosition.z = Number(position.z) * threeData.scaleRate;
  }
}

// 渲染场景
function render() {
  if (renderer && scene && camera) {
    renderer.render(scene, camera);
  }
}

// 调整渲染器大小
function resizeRenderer() {
  if (!renderer || !camera || !threeBoxRef.value) return;

  threeData.width = props.renderParams.width;
  threeData.height = props.renderParams.height;

  if (camera) {
    camera.aspect = threeData.width / threeData.height;
    camera.updateProjectionMatrix();
  }

  if (renderer) {
    renderer.setSize(threeData.width, threeData.height);
  }

  updateAllSensorLabels();
  render();
}

// 添加初始数据
function addInitialData() {
  if (!scene) return;

  // 添加一些初始传感器
  const initialSensors = [
    { longitude: 90, latitude: 45 },
    { longitude: 180, latitude: 90 },
    { longitude: 270, latitude: 135 },
    { longitude: 45, latitude: 30 },
    { longitude: 225, latitude: 60 }
  ];

  initialSensors.forEach(sensor => {
    addSensor(sensor.longitude, sensor.latitude);
  });

  // 添加一些初始点
  const radius = getSphereRadius();
  const initialPoints = [
    { x: radius * 0.5, y: radius * 0.5, z: radius * 0.5 },
    { x: -radius * 0.8, y: radius * 0.2, z: radius * 0.1 },
    { x: radius * 0.3, y: -radius * 0.6, z: radius * 0.4 }
  ];

  initialPoints.forEach((point, index) => {
    addPoint(point.x, point.y, point.z, `initial_point_${index + 1}`);
  });
}

// 监听参数变化
watch(() => props.locateSetting, (newVal) => {
  console.log('SphereFace3D - Locate setting changed:', newVal);
  updateSphere();
}, { deep: true, immediate: true });

watch(() => props.renderParams, (newVal) => {
  console.log('SphereFace3D - Render params changed:', newVal);
  resizeRenderer();
}, { deep: true, immediate: true });

// 组件挂载时初始化
onMounted(() => {
  console.log('SphereFace3D component mounted');
  // 初始化Three.js场景
  initThree();

  // 延迟添加初始数据
  setTimeout(() => {
    addInitialData();
  }, 500);
});

// 组件卸载时清理
onUnmounted(() => {
  if (renderer) {
    renderer.dispose();
  }
  if (controls) {
    controls.dispose();
  }

  // 移除事件监听器
  window.removeEventListener('mousemove', handleMouseMove);

  // 清理所有3D对象
  if (scene) {
    scene.clear();
  }

  // 清理引用
  axisLineMeshes = [];
  axisTextMeshes = [];
  sensors.value = [];
  points.value = [];
});

// 暴露方法给父组件
defineExpose({
  addSensor,
  removeSensor,
  addPoint,
  removePoint,
  geoTo3D,
  threeDToGeo,
  mousePosition
});
</script>

<style scoped lang="scss">
.sphere-face-3d {
  width: 100%;
  height: 100%;
  background-color: #f0f4f8;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  overflow: hidden;
  position: relative;
  display: flex;
  flex-direction: column;
}

.title {
  position: relative;
  top: 0;
  left: 0;
  z-index: 100;
  width: 100%;
  text-align: center;
  font-size: 11px;
  background-color: transparent; /* 完全透明 */
}

.view-content {
  width: 100%;
  height: 100%;
  position: relative;
}

/* 传感器标签样式 - 参考d3-bak.vue */
.sensor-label {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  display: inline-block;
  line-height: 1;
  color: orangered;
  font-weight: bold;
  font-size: 13px;
  pointer-events: none; /* 避免影响鼠标交互 */
}
</style>
